# Copyright 2008 Ilya Novoselov
#
# This file is part of TyuChat.
#
# TyuChat is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# TyuChat is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with TyuChat.  If not, see <http://www.gnu.org/licenses/>.

from twisted.web2 import resource, http, responsecode, iweb
from zope.interface import implements

import twistedpie

class ResourceNode():
    """Dispatch requests between mounted applications."""
    
    implements(iweb.IResource)
    
    def __init__(self):
        self.children = {}
        self.mountedResource = None

    def locateChild(self, request, segments):
        # Try to get child resource,
        child = self.children.get(segments[0], None)
        
        # Return child resource if found.
        if child:
            return child, segments[1:]
        
        # Mounted resource.
        if self.mountedResource:
            return self.mountedResource, segments
        
        # Nothing, give up.
        return None, []


class DefaultDispatcher(resource.LeafResource):
    queryArgsCharset = 'utf-8'
    
    def __init__(self, app):
        self.appObject = app
    
    def callResource(self, res, req, segments, args):
        twistedpie.req = req
        response = res(*segments, **args)
        twistedpie.req = None
        return response
    
    def render(self, req):
        segments = req.postpath[:]
        
        # Get args.
        args = {}
        for key, values in req.args.iteritems():
            # Decode values, assuming default charset.
            args[key] = [value.decode(self.queryArgsCharset) for value in
                         values]
        
        # mix in files
        args.update(req.files)
        
        # Flatten args
        for key, value in args.iteritems():
            if len(value) == 1:
                args[key] = value[0]

        currentResource = self.appObject
        while len(segments):
            # Retrieve path fragment.
            resource_name = segments.pop(0)
            
            # Skip empty segment.
            if not len(resource_name):
                continue
            
            # Try to get the resource from current resource.
            try:
                currentResource = getattr(currentResource, resource_name)
            except AttributeError:
                return http.Response(responsecode.NOT_FOUND)
            
            if getattr(currentResource, 'exposed', None):
                return self.callResource(currentResource, req, segments, args)
        
        res = getattr(currentResource, 'index', None)
        if getattr(res, 'exposed', None):
            return self.callResource(res, req, segments, args)
    
        return http.Response(responsecode.NOT_FOUND)